/* hal_etmr.c */
#include "hal_etmr.h"

/* flags and interrupts. */

uint32_t eTMR_GetStatusFlags(eTMR_Type * base)
{
    return base->STS;
}

void eTMR_ClearStatusFlags(eTMR_Type * base, uint32_t flags)
{
    base->STS = flags;
}

uint32_t eTMR_GetIoPinLevels(eTMR_Type * base)
{
    return base->IOSTS;
}

void eTMR_EnableInterrupts(eTMR_Type * base, uint32_t interrupts)
{
    base->INTE |= interrupts;
}

void eTMR_DisableInterrupts(eTMR_Type * base, uint32_t interrupts)
{
    base->INTE &= ~interrupts;
}

/* counter. */

void eTMR_DoLoadOk(eTMR_Type * base)
{
    base->SYNC |= eTMR_SYNC_LDOK_MASK;
}

void eTMR_InitCounter(eTMR_Type * base, eTMR_CounterInit_Type * init)
{
    uint32_t tmp32 = 0u;

    base->CTRL = 0u; /* disable the counter. */
    base->CNT = 0u; /* reset the counter value. */

    if (init->EnableRunningOnDebug)
    {
        tmp32 |= eTMR_CTRL_DBGDIS_MASK;
    }
    
    tmp32 |= eTMR_CTRL_CLKPRS(init->ClkFreqHz / init->StepFreqHz )
           | eTMR_CTRL_CLKSRC(init->ClkSrc)
           ;
    
    if (init->EnableGlobalCountingBase)
    {
        tmp32 |= eTMR_CTRL_GLOBEN_MASK;
    }
    
    base->CTRL = tmp32; /* setup without starting counter. */
    
    /* keep the SYNC as default, and setup in future according to requirements. */
    //base->SYNC = 0u;
    base->SYNC = eTMR_SYNC_REGLD(1); /* updaet all values when matching the mod value. */
    base->OTRIG = 0u;
    
    base->MOD  = init->ModVal;
    //base->INIT = init->InitVal;
    //base->MID  = init->MidVal;
    
    //base->SYNC |= eTMR_SYNC_LDOK_MASK; /* do load the value registers. */
    //eTMR_DoLoadValues(base);
}

uint32_t eTMR_GetCounterValue(eTMR_Type * base)
{
    return base->CNT;
}

void eTMR_StartCounter(eTMR_Type * base)
{
    base->CTRL |= eTMR_CTRL_EN_MASK;
}

void eTMR_StopCounter(eTMR_Type * base)
{
    base->CTRL &= ~eTMR_CTRL_EN_MASK;
}

/* channel with output compare mode. */

void eTMR_InitChannelOutputCompare(eTMR_Type * base, uint32_t channel, eTMR_ChannelOutputCompareInit_Type * init)
{
    //uint32_t tmp32 = base->CTRL;
    uint32_t chn_pair = channel >> 1u;
    
    /* complementary mode for chair pair. */
    if (init->EnableComplementaryMode)
    {
        base->CTRL |= ((1u << chn_pair) << eTMR_CTRL_COMPL01_SHIFT);
    }
    else
    {
        base->CTRL &= ~((1u << chn_pair) << eTMR_CTRL_COMPL01_SHIFT);
    }
#if 0
    /* enable to generate double switch signal. */
    if (init->EnableDoubleSwitchMode)
    {
        base->CTRL |= ((1u << chn_pair) << eTMR_CTRL_DBSW01_SHIFT);
    }
    else
    {
        base->CTRL &= ~((1u << chn_pair) << eTMR_CTRL_DBSW01_SHIFT);
    }
#endif
    switch (init->InitOutputLogic)
    {
        case eTMR_OutputLogic_Logic0:
            //base->CHINIT &= ~((1u << channel) << eTMR_CHINIT_CH0INITV_SHIFT);
            base->CHINIT &= ~((1u << channel) << eTMR_CHINIT_CH0INIT_SHIFT) ;
            break;
        case eTMR_OutputLogic_Logic1:
            //base->CHINIT |=  ((1u << channel) << eTMR_CHINIT_CH0INITV_SHIFT);
            base->CHINIT |=  ((1u << channel) << eTMR_CHINIT_CH0INIT_SHIFT) ;
            break;
        default:
            break;
    }
    
    uint32_t ch_ctrl = eTMR_CH_CTRL_LDEN_MASK; /* always enable loading the new setting values. */
    if (init->EnableDma)
    {
        ch_ctrl |= eTMR_CH_CTRL_DMAEN_MASK;
    }
    
    ch_ctrl |= eTMR_CH_CTRL_VAL0CMP(init->OutputCompareEventForVal0)
            |  eTMR_CH_CTRL_VAL1CMP(init->OutputCompareEventForVal1)
            |  eTMR_CH_CTRL_CHMODE(2) /* channel output compare mode. */
            ;

    if (init->EnableTriggerOutOnVal0)
    {
        ch_ctrl |= eTMR_CH_CTRL_VAL0TEN_MASK;
    }
    if (init->EnableTriggerOutOnVal1)
    {
        ch_ctrl |= eTMR_CH_CTRL_VAL1TEN_MASK;
    }
    base->CH[channel].CTRL = ch_ctrl;
    
    base->CH[channel].VAL0 = init->Val0;
    base->CH[channel].VAL1 = init->Val1;

}

void eTMR_UpdateChannelOutputCompareValue0(eTMR_Type * base, uint32_t channel, uint32_t val)
{
    base->CH[channel].VAL0 = val;
}

void eTMR_UpdateChannelOutputCompareValue1(eTMR_Type * base, uint32_t channel, uint32_t val)
{
    base->CH[channel].VAL1 = val;
}

/* channel with input capture mode. */

void eTMR_InitChannelInputCapture(eTMR_Type * base, uint32_t channel, eTMR_ChannelInputCaptureInit_Type * init)
{
    base->CH[channel].CTRL = 0u;
    
    base->CH[channel].CTRL = eTMR_CH_CTRL_CHMODE(3) /* channel input capture mode. */
                           | eTMR_CH_CTRL_CAPEDGE(init->InputCaptureEvent)
                            ;
}

uint32_t eTMR_GetChannelInputCaptureValue(eTMR_Type * base, uint32_t channel)
{
    return base->CH[channel].CVAL;
}

/* quad decoder. */

void eTMR_GetDecoderStatus(eTMR_Type * base, eTMR_QDecoderDirection_Type * dir, uint16_t * val)
{
    *dir = ((base->STS & eTMR_STS_QDDIR_MASK) == 0u) ? eTMR_QDecoderDirection_Increase : eTMR_QDecoderDirection_Decrease;
    *val = base->QDCNT;
}

void eTMR_InitQDecoder(eTMR_Type * base, eTMR_QDecoderInit_Type * init)
{    
    base->QDCTRL = 0u;
    if (init)
    {
        uint32_t tmp32 = eTMR_QDCTRL_QDEN_MASK;
        tmp32 |= eTMR_QDCTRL_QDFCNT(init->FilterSampleCount)
               | eTMR_QDCTRL_QDFPER(init->FilterSamplePeriod)
               | eTMR_QDCTRL_QDCLKPRS(init->PreDiv)
               | eTMR_QDCTRL_QDMODE(init->QDecoderMode)
               ;
        
        if (init->EnableInvertPhaseA)
        {
            tmp32 |= eTMR_QDCTRL_PHAPOL_MASK;
        }
        
        if (init->EnableInvertPhaseB)
        {
            tmp32 |= eTMR_QDCTRL_PHBPOL_MASK;
        }
        
        //base->QDINIT = init->InitVal;
        //base->QDMOD = init->ModVal;
        
        base->QDCTRL = tmp32; /* enable the quad decoder. */
    }
}

/* fault input. */
void eTMR_EnableFaultInputs(eTMR_Type * base, uint32_t mask, bool enable)
{
    if (enable)
    {
        base->FAULT |= mask;
    }
    else
    {
        base->FAULT &= ~mask;
    }
}

/* EOF. */

